/*****************************
 *@file: BaseFightComp
 *@author: 陈吕唐
 *@desc: 基础战斗逻辑类(只写战斗逻辑,不调用组件相关)
 *@date: 2024-02-27	16:16
 *****************************/

import { Component, _decorator } from 'cc';
import GameFormula from '../GameFormula';
import { MGameEvent } from './MGameEvent';
import IBaseCure from './data/IBaseCure';
import IBaseFightAttribute from './data/IBaseFightAttribute';
import IBaseHurt from './data/IBaseHurt';
import { FightGroupEnum } from './enum/FightGroupEnum';
import { HurtTypeEnum } from './enum/HurtTypeEnum';
import { LifeEnum } from './enum/LifeEnum';
import IBaseCureBullet from './fight/IBaseCureBullet';
import IBaseFight from './fight/IBaseFight';
import IBaseInjureBullet from './fight/IBaseInjureBullet';
import IFightAction from './fight/IFightAction';
import IBaseSkill from './skill/IBaseSkill';
import BaseAction from './strategy/BaseAction';
const { ccclass, property } = _decorator;

@ccclass('BaseFightLogic')
export class BaseFightLogic extends Component implements IBaseFight {

    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    /****************************************************************************************************************
     *Property 定义变量
     ****************************************************************************************************************/
    /***********************************
     * 属性
     ***********************************/
    protected _lifeState: LifeEnum = LifeEnum.INIT;

    protected _group: FightGroupEnum = FightGroupEnum.UNKNOWN;

    protected _hp: number = 0;

    protected _maxHp: number = 0;

    protected _atk: number = 0;

    protected _def: number = 0;

    protected _spd: number = 0;
    /***********************************
     * 技能
     ***********************************/
    /**
     * 技能数据
     */
    protected skill: IBaseSkill = undefined;
    /***************************************
     * 
     ***************************************/
    /**
     * 队友
     */
    public team: BaseFightLogic[] = [];


    /**
     * 敌人
     */
    protected _enemy: BaseFightLogic[] = [];
    /***************************************
     * 策略
     ***************************************/
    /**
     * 当前行动策略
     */
    protected fightAction: IFightAction = undefined;
    /***********************************
     * 事件分发器
     ***********************************/
    /***************************************************************
     *PropertyUI 引用的控件
     ***************************************************************/
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/
    /***********************************
     * 战斗单位生命周期
     ***********************************/
    /**
     * 根据属性数据初始战斗单位
     * @param value 
     */
    public init(value: IBaseFightAttribute) {
        this.maxHp = value.hp;
        this.hp = value.hp;
        this.atk = value.atk;
        this.def = value.def;
        this.spd = value.spd;
        this.lifeState = LifeEnum.INIT;
        this.fightAction = new BaseAction(this);
    }


    /**
     * 开始行动(注意先初始化完)
     */
    public fightStart(): void {
        this.lifeState = LifeEnum.LIFE;
    }

    /**
     * 战斗单位执行行动
     */
    public async action(): Promise<boolean> {

        let bool = await this.fightAction.action();

        if (bool) {
            this.emit(MGameEvent.FightEvent.ACTION_COMPLETE, this);
        }

        return bool;
    }

    /**
     * 战斗单位死亡
     */
    public fightDead(): void {
        this.emit(MGameEvent.FightEvent.DEAD_STATE, this);
        this.lifeState = LifeEnum.DEAD;
    }
    /***********************************
     * 
     ***********************************/
    /**
     * 受到攻击
     * @param bullet 子弹数据
     * @return 伤害数据
     */
    public hurt(bullet: IBaseInjureBullet): IBaseHurt {

        if (this.lifeState != LifeEnum.LIFE) {
            console.warn('当前状态异常不能被攻击');
            return { value: 0, type: HurtTypeEnum.UNKNOWN };
        }

        let damage = 0;
        switch (bullet.type) {
            case HurtTypeEnum.NORMAL:
                damage = GameFormula.normalHurt(bullet.value, this.def);
                break;
            case HurtTypeEnum.TRUTH:
                damage = bullet.value
                break;
            default:
                damage = GameFormula.normalHurt(bullet.value, this.def);
                console.warn('hurt type error');
                break;
        }

        let hurt: IBaseHurt = { value: damage, type: bullet.type };
        this.emit(MGameEvent.FightEvent.INJURE_EVENT, hurt);
        this.hp -= damage;
        return hurt;
    }

    /**
     * 受到治疗
     * @param bullet 治疗子弹数据
     */
    public curt(bullet: IBaseCureBullet): IBaseCure {
        let value = bullet.value;
        this.hp += value;
        let cure: IBaseCure = { value: value };
        return cure;
    };
    /***********************************
     * 
     ***********************************/
    /**
     * 更新游戏时间 
     * @param dt 秒
     */
    protected updateGame(dt: number): void {
        if (this.lifeState != LifeEnum.LIFE) {
            return;
        }
        this.emit(MGameEvent.FightEvent.UPDATE_TIME, dt)
    }


    protected updateHp(hp: number): void {
        this.emit(MGameEvent.FightEvent.UPDATE_HP, hp);
        if (hp <= 0) {
            this.fightDead();
        }
    }
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    /**
     * 发送战斗相关事件
     * @param type 
     * @param data 
     */
    protected emit(type: string, data: any) {
        if (this.lifeState != LifeEnum.LIFE) {
            return;
        }
        this.node.emit(type, data);
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
    public get lifeState(): LifeEnum {
        return this._lifeState;
    }
    protected set lifeState(value: LifeEnum) {
        this._lifeState = value;
    }

    /**
     * 当前敌人
     */
    public get enemy(): BaseFightLogic[] {
        return this._enemy;
    }
    /****************************************************
     * 战斗单位属性
     ****************************************************/
    /**
     * 最大生命值
     */
    public get maxHp(): number {
        return this._maxHp;
    }

    protected set maxHp(value: number) {
        this._maxHp = value;
    }

    public get hp(): number {
        return this._hp;
    }
    protected set hp(value: number) {
        value = Math.max(value, 0);
        value = Math.min(value, this.maxHp);
        this.updateHp(value);
        this._hp = value;
    }
    public get def(): number {
        return this._def;
    }
    protected set def(value: number) {
        this._def = value;
    }

    public get atk(): number {
        return this._atk;
    }

    protected set atk(value: number) {
        this._atk = value;
    }

    public get group(): FightGroupEnum {
        return this._group;
    }
    protected set group(value: FightGroupEnum) {
        this._group = value;
    }

    public get spd(): number {
        return this._spd;
    }
    protected set spd(value: number) {
        this._spd = value;
    }
}


